﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using PMS.XCMG.Entity;
using PMS.XCMG.IBusiness;
using PMS.XCMG.Util;
using PMS.XCMG.Models;

namespace PMS.XCMG.Business
{
    public class Sys_UserBusiness : BusRepository<Sys_User>, ISys_UserBusiness, IScopedDependency
    {
        private IServiceProvider SvcProvider { get; set; }
        public Sys_UserBusiness(GDbContext context, IServiceProvider svcProvider)
            : base(context)
        {
            this.SvcProvider = svcProvider;
        }

        public async Task<Sys_User> LoginAsync(LoginQM data)
        {
            var user = await this.GetAsync(w => w.UserName == data.UserName && w.Password == data.Password && w.Status== "Enable");
            if (user == null)
                throw new Exception("帐号密码不正确");
            return user;
        }

        public async Task<PageResult<Sys_User>> GetPageResultAsync(PageInput<Sys_UserQM> query)
        {
            var queryable = this.GetQueryable(true);
            var search = query.Search;
            if (!search.Keyword.IsNullOrEmpty())
                queryable = queryable.Where(w => w.Code.Contains(search.Keyword) || w.Name.Contains(search.Keyword) || w.UserName.Contains(search.Keyword));

            var result = await this.GetPageResultAsync(queryable, query);
            if (!search.Id.IsNullOrEmpty())
            {
                if (!result.Data.Any(w => w.Id == search.Id))
                {
                    var idOne = await this.GetQueryable(true).SingleOrDefaultAsync(w => w.Id == search.Id);
                    result.Data.Add(idOne);
                    result.Total += 1;
                }
            }
            return result;
        }

        public async Task<dynamic> GetUserInfo(string id)
        {
            var user = await this.GetAsync(id);
            var roleIds = await this.GetQueryable<Sys_UserRole>(true).Where(w => w.UserId == id).Select(s => s.RoleId).ToListAsync();
            //var roles = await this.GetQueryable<Sys_Role>(true).Where(w => roleIds.Contains(w.Id)).ToListAsync();

            var roleMenuIds = await this.GetQueryable<Sys_RoleMenu>(true).Where(w => roleIds.Contains(w.RoleId)).ToListAsync();
            //var roleLookup = roleMenuIds.ToLookup(k => k.RoleId, v => v.MenuId);
            var menuIds = roleMenuIds.Select(s => s.MenuId).ToList();
            var menus = await this.GetQueryable<Sys_Menu>(true).Where(w => menuIds.Contains(w.Id)).ToListAsync();

            var actionIds = await this.GetQueryable<Sys_RoleAction>(true).Where(w => roleIds.Contains(w.RoleId)).Select(s => s.ActionId).ToListAsync();
            var actions = await this.GetQueryable<Sys_Action>(true).Where(w => actionIds.Contains(w.Id) && menuIds.Contains(w.MenuId)).ToListAsync();

            foreach (var menu in menus)
            {
                menu.Actions = actions.Where(w => w.MenuId == menu.Id).ToList();
            }

            var vm = new
            {
                id = user.Id,
                name = user.Name,
                username = user.UserName,
                companyId = user.CompanyId,
                role = new
                {
                    id = "role",
                    name = "角色",
                    permissions = menus.Select(s => new
                    {
                        permissionId = s.Code,
                        permissionName = s.Name,
                        actions = s.Actions.Select(a => new { action = a.Code, describe = a.Name, defaultCheck = true }).ToList()
                    }).ToList()
                }
            };

            return vm;
        }

        public async Task<List<Sys_Menu>> GetUserMenu(string id)
        {
            var roleIds = await this.GetQueryable<Sys_UserRole>(true).Where(w => w.UserId == id).Select(s => s.RoleId).ToListAsync();
            var roleMenuIds = await this.GetQueryable<Sys_RoleMenu>(true).Where(w => roleIds.Contains(w.RoleId)).ToListAsync();
            var menuIds = roleMenuIds.Select(s => s.MenuId).ToList();
            var menus = await this.GetQueryable<Sys_Menu>(true).Where(w => menuIds.Contains(w.Id)).OrderBy(o => o.ParentId).ThenBy(o => o.Seq).ToListAsync();
            return menus;
        }

        public override async Task<int> AddOrUpdateAsync(Sys_User entity)
        {
            var dbEntity = await this.GetAsync(entity.Id, true);
            if (dbEntity != null)
            {
                if (entity.Password == "")
                    entity.Password = dbEntity.Password;
                return await this.UpdateAsync(entity);
            }
            else
                return await this.AddAsync(entity);
        }
    }
}